#include <math.h>
#include "vector.h"

using namespace std;

Vector::Vector()
{
	v[0] = 0;
	v[1] = 0;
	v[2] = 0;
}

Vector::Vector(const Vector &vec)
{
	v[0] = vec.v[0];
	v[1] = vec.v[1];
	v[2] = vec.v[2];
}

Vector::Vector(float x, float y, float z)
{
	v[0] = x;
	v[1] = y;
	v[2] = z;
}

float &Vector::operator[](int index)
{
	return v[index];
}

float Vector::operator[](int index) const
{
	return v[index];
}

Vector Vector::operator*(float scale) const
{
	return Vector(v[0] * scale, v[1] * scale, v[2] * scale);
}

Vector Vector::operator/(float scale) const
{
	return Vector(v[0] / scale, v[1] / scale, v[2] / scale);
}

Vector Vector::operator+(const Vector &other) const
{
	return Vector(v[0] + other.v[0], v[1] + other.v[1], v[2] + other.v[2]);
}

Vector Vector::operator-(const Vector &other) const
{
	return Vector(v[0] - other.v[0], v[1] - other.v[1], v[2] - other.v[2]);
}

Vector Vector::operator-() const
{
	return Vector(-v[0], -v[1], -v[2]);
}

const Vector &Vector::operator*=(float scale)
{
	v[0] *= scale;
	v[1] *= scale;
	v[2] *= scale;
	return *this;
}

const Vector &Vector::operator/=(float scale)
{
	v[0] /= scale;
	v[1] /= scale;
	v[2] /= scale;
	return *this;
}

const Vector &Vector::operator+=(const Vector &other)
{
	v[0] += other.v[0];
	v[1] += other.v[1];
	v[2] += other.v[2];
	return *this;
}

const Vector &Vector::operator-=(const Vector &other)
{
	v[0] -= other.v[0];
	v[1] -= other.v[1];
	v[2] -= other.v[2];
	return *this;
}

const bool Vector::operator==(const Vector &other)
{
	return (v[0] == other[0] && v[1] == other[1] && v[2] == other[2]);
}

const bool Vector::operator==(float number)
{
	return (v[0] == number && v[1] == number && v[2] == number);
}

float Vector::magnitude() const
{
	return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}

float Vector::magnitudeSquared() const
{
	return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
}

Vector Vector::normalize() const
{
	float m = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
	return Vector(v[0] / m, v[1] / m, v[2] / m);
}

float Vector::dot(const Vector &other) const
{
	return v[0] * other.v[0] + v[1] * other.v[1] + v[2] * other.v[2];
}

Vector Vector::cross(const Vector &other) const
{
	return Vector(v[1] * other.v[2] - v[2] * other.v[1],
				 v[2] * other.v[0] - v[0] * other.v[2],
				 v[0] * other.v[1] - v[1] * other.v[0]);
}

Vector operator*(float scale, const Vector &v)
{
	return v * scale;
}

ostream &operator<<(ostream &output, const Vector &v)
{
	cout << '(' << v[0] << ", " << v[1] << ", " << v[2] << ')';
	return output;
}